package com.adams.encache.mechanism;

import java.lang.reflect.AnnotatedElement;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.persistence.Table;

import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;

public class CacheUtil
{
	public static String VIEW_CONFIG_DATA_CACHE_NAME = "viewconfigdatacache";

	public static String VIEW_SERVICE_CACHE_NAME = "viewservicecache";

	public static String VIEW_DATA_CACHE_NAME = "viewdatacache";

	// 保存表名与sql语句的映射关系，表名与sql语句是多对多的关系 用于加快算法
	public static String cacheSqlsByTablecode = "CacheUtil_cacheSqlsByTablecode";

	/**
	 * Description : 根据缓存名 获取缓存
	 * 
	 * @param cacheName
	 * @return
	 * 
	 */
	public static Cache getCache(String cacheName)
	{
		CacheManager manager = CacheManager.getInstance();
		Cache cache = manager.getCache(cacheName);
		if (cache == null)
		{
			manager.addCache(cacheName);
			cache = manager.getCache(cacheName);
		}
		return cache;
	}

	/**
	 * Description : 根据缓存名及缓存key 获取缓存Map对象
	 * 
	 * @param cacheKey
	 * @return
	 * 
	 */
	@SuppressWarnings("unchecked")
	public static Map getCacheMap(String cacheName, String cacheKey)
	{
		Cache cache = CacheUtil.getCache(cacheName);
		Element element = cache.get(cacheKey);
		if (null == element)
		{
			element = new Element(cacheKey, new HashMap());
		}
		cache.put(element);
		return (Map) element.getValue();
	}

	/**
	 * Description : 根据缓存名及缓存key 放入配置信息缓存
	 * 
	 * @param cacheKey
	 * @param cacheObject
	 * 
	 */
	@SuppressWarnings("unchecked")
	public static void put2DataCacheMap(String cacheName, String cacheKey,
			Map cacheObject)
	{
		Cache cache = CacheUtil.getCache(cacheName);
		Element element = new Element(cacheKey, cacheObject);
		cache.put(element);
	}

	/**
	 * Description : 根据annotation得到bean相关的表名
	 * 
	 * @param classname
	 * 
	 */
	@SuppressWarnings("unchecked")
	public static void clearCacheByClass(Class classname)
	{
		AnnotatedElement target = classname;
		Table annotation = target.getAnnotation(Table.class);
		if (null == annotation)
		{
			return;
		}
		String tablecode = annotation.name();
		clearCacheByTablecode(tablecode);
	}

	/**
	 * Description : 根据表名清空查询数据缓存
	 * 
	 * @param tablecode
	 * 
	 */
	@SuppressWarnings("unchecked")
	public static void clearCacheByTablecode(String tablecode)
	{
		if (null == tablecode || tablecode.trim().length() == 0)
		{
			return;
		}
		tablecode = tablecode.trim().toUpperCase();
		Map tableMap = getCacheMap(VIEW_SERVICE_CACHE_NAME,
				cacheSqlsByTablecode);
		if (tableMap.containsKey(tablecode))
		{
			Set sqls = (Set) tableMap.get(tablecode);
			if (null != sqls)
			{
				Cache cache = CacheUtil
						.getCache(CacheUtil.VIEW_DATA_CACHE_NAME);
				for (Iterator it = sqls.iterator(); it.hasNext();)
				{
					String sql = (String) it.next();
					cache.remove(sql);
				}
			}
			tableMap.remove(tablecode);
		}
	}

	/**
	 * Description : 清除表缓存中的垃圾数据
	 * 
	 * 
	 */
	@SuppressWarnings("unchecked")
	public static void clearTableCacheRubbishData()
	{
		// 得到缓存中现有的sql key
		Cache cache = CacheUtil.getCache(CacheUtil.VIEW_DATA_CACHE_NAME);
		List cacheSqls = cache.getKeys();
		Set<String> sqlSet = new HashSet<String>();
		for (Iterator it = cacheSqls.iterator(); it.hasNext();)
		{
			String sql = (String) it.next();
			sqlSet.add(sql);
		}

		// 删除tableMap中没有sql的table key
		Map tableMap = getCacheMap(VIEW_SERVICE_CACHE_NAME,
				cacheSqlsByTablecode);
		Set tableSet = tableMap.keySet();
		Set<String> clearTableSet = new HashSet<String>();
		for (Iterator tableit = tableSet.iterator(); tableit.hasNext();)
		{
			String table = (String) tableit.next();
			Set sqls = (Set) tableMap.get(table);
			if (null != sqls)
			{
				for (Iterator sqlit = sqls.iterator(); sqlit.hasNext();)
				{
					String sql = (String) sqlit.next();
					if (!sqlSet.contains(sql))
					{
						sqlit.remove();
					}
				}
				if (sqls.size() == 0)
				{
					sqls = null;
				}
			}
			if (null == sqls)
			{
				clearTableSet.add(table);
				tableMap.put(table, null);
			}
		}

		for (String clearTable : clearTableSet)
		{
			tableMap.remove(clearTable);
		}
	}

}
